import AppSettings from "@runtime/base/AppSettings";
import { ClientOpcode } from "@runtime/generate/message/ClientOpcode";
import { ServerOpcode } from "@runtime/generate/message/ServerOpcode";

/**
 * 消息码组件
 */
export default class OpcodeComponent {
    private static instance: OpcodeComponent = new OpcodeComponent();
    /**
     * 消息码组件
     */
    public static get Default(): OpcodeComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.AddAllPair();
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        this.map.clear();
    }

    private ignoreOpcodeSet: Set<number> = new Set<number>([
        ClientOpcode.LabelUpdateMessage,
        ClientOpcode.DeviceUpdateMessage,
        ClientOpcode.InertialNavigationCalibrationLabelUpdateMessage,
        ClientOpcode.InertialNavigationProtocolDataUpdateMessage,
    ]);

    private map: Map<number, string> = new Map();

    public LogMsg(caller: string, opcode: number, message: Object & Partial<{ Opcode: number }>): void {
        if (!AppSettings.Default.IsDevelopment) {
            return;
        }

        if (this.ignoreOpcodeSet.has(opcode)) {
            return;
        }

        delete message.Opcode;

        window.Logger.Debug(`${caller.padEnd(16, ' ')} ${this.map.get(opcode)!.padEnd(64, ' ')} ${JSON.stringify(message)}`);
    }

    private AddAllPair(): void {
        for (const [name, opcode] of Object.entries(ClientOpcode)) {
            this.map.set(opcode, name);
        }
        for (const [name, opcode] of Object.entries(ServerOpcode)) {
            this.map.set(opcode, name);
        }
    }
}